/*
Copyright (C) 2008 raohmaru <http://www.raohmaru.com>

This file is part of Raohmaru AS3 Framework.

Raohmaru AS3 Framework is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Raohmaru AS3 Framework is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with Raohmaru AS3 Framework.  If not, see <http://www.gnu.org/licenses/>.
*/

package jp.raohmaru.effects
{
import flash.display.DisplayObject;
import flash.filters.ColorMatrixFilter;

import jp.raohmaru.geom.ColorMatrixEx;

/**
 * La clase effects.ColorModifier permite aplicar de una manera rápida efectos de color a objetos de visualización.
 * Una instancia de ColorModifier Añade un filtro ColorMatrixFilter al objeto DisplayObject relacionado, permitiendo modificar los valores
 * de brillo, contraste, saturación y tonalidad.<br>
 * Para hacer la transformación de color, se utiliza el objeto ColorMatrixEx.
 * @see jp.raohmaru.geom.ColorMatrixEx
 * @see flash.filters.ColorMatrixFilter
 * @author raohmaru
 * @version 2.0
 */
public class ColorModifier
{
  private var _target : DisplayObject,
        _matrix :ColorMatrixEx,
        _brightness :Number = 0,        _contrast :Number = 0,        _saturation :Number = 0,
        _hue :Number = 0;

  /**
  * Establece el objeto de visualización en el que se aplicarán los efectos de color.
  */
  public function get target() : DisplayObject
  {
    return _target;
  }
  public function set target(value : DisplayObject) : void
  {
    _target = value;
  }

  /**
   * Cambia el brillo del objetivo especificado. Los valores van desde -1 (completamente oscuro), 0 (normal) a 1 (completamente brillante).<br>
   * @param amount Cantidad de brillo a aplicar (-1:completamente oscuro, 0:normal, 1:completamente brillante)
   * @default 0
   * @example
  <listing version="3.0">
  import jp.raohmaru.effects.Color;

  var color_mod : ColorModifier = new ColorModifier(some_mc);
  color_mod.brightness = 0.5;</listing>
   */
  public function get brightness() : Number
  {
    //var matrix : Array = EffectUtil.getColorMatrix(target);
    //return matrix[4]/255;

    return _brightness / 255;
  }
  public function set brightness(amount : Number) : void
  {
    _brightness = amount * 255;
    update();
  }

  /**
   * Cambia el contraste del objetivo especificado. Los valores van desde -1 (sin contrase), 0 (normal) a 1 (contrase máximo).<br>
   * @param amount Cantidad de contraste a aplicar (-1:sin contrase, 0:normal, 1:contrase máximo)
   * @default 0
   * @example
  <listing version="3.0">
  import jp.raohmaru.effects.Color;

  var color_mod : ColorModifier = new ColorModifier(some_mc);
  color_mod.contrast = 5.5;</listing>
   */
  public function get contrast() : Number
  {
    return _contrast / 100;
  }
  public function set contrast(amount : Number) : void
  {
    _contrast = amount * 100;
    update();
  }

  /**
   * Cambia la saturación del objetivo especificado. Los valores van desde -1 (completamente desaturado), 0 (normal) a 8+ (muy saturado).
   * @see flash.filters.ColorMatrixFilter
   * @param amount Cantidad de saturación a aplicar (-1:completamente desaturado, 0:normal, 8+:muy saturado)
   * @default 0
   * @example
  <listing version="3.0">
  import jp.raohmaru.effects.Color;

  var color_mod : ColorModifier = new ColorModifier(some_mc);
  color_mod.saturation = 10;</listing>
   */
  public function get saturation() : Number
  {
    //var matrix : Array = EffectUtil.getColorMatrix(target);
    //return -matrix[5]/LUMA_R;

    return _saturation / 100;
  }
  public function set saturation(amount : Number) : void
  {
    _saturation = amount * 100;
    update();
  }

  /**
   * Cambia el valor del tono del objetivo especificado. Los valores van desde -180 a 180 (en grados).
   * @see flash.filters.ColorMatrixFilter
   * @param amount Cantidad de desplazamiento del tono en grados (de -180 a 180)
   * @default 0
   * @example
  <listing version="3.0">
  import jp.raohmaru.effects.Color;

  var color_mod : ColorModifier = new ColorModifier(some_mc);
  color_mod.hue = 120;</listing>
   */
  public function get hue() : Number
  {
    return _hue;
  }
  public function set hue(amount : Number) : void
  {
    _hue = amount;
    update();
  }



  /**
   * Crea una instancia de ColorModifier.
   * @param target Un objeto de visualización en el que se aplicarán los efectos de color
   */
  public function ColorModifier(target : DisplayObject)
  {
    _target = target;
  }

  /**
   * Convierte a escala de grises un objeto DisplayObject. Este método es un atajo a <code>ColorModifier.saturation()</code>.
   * @param amount Porcentaje que se aplica al efecto, expresado como valor decimal entre <code>0</code> (normal) y <code>1</code> (en escala de grises)
   * @see #saturation
   */
  public function toGrayscale(amount : Number = 1) : void
  {
    if(amount < 0) amount = 0;
    if(amount > 1) amount = 1;

    saturation = amount*-1;
  }

  /**
   * Invierte los colores del objeto DisplayObject. Este método es un atajo a <code>contrast = -4</code>. Para restaurar la imagen, utilizar
   * <code>contrast = 0</code>.
   * @see #contrast
   */
  public function invert() : void
  {
    contrast = -4;
  }

  /**
   * Restaura los valores de brillo, contraste, saturación y tono del objeto DisplayObject asociado.
   */
  public function restore() : void
  {
    _brightness = 0;    _contrast = 0;
    _saturation = 0;    _hue = 0;
    EffectUtil.removeFilter(_target, ColorMatrixFilter);
  }

  /**
   * Obtiene una copia de la matriz de transformación utilizada por la instancia actual de ColorModifier.
   * @see jp.raohmaru.geom.ColorMatrixEx
   */
  public function getColorMatrix() :Array
  {
    return (_matrix) ? _matrix.toArray() : EffectUtil.getEmptyColorMatrix();
  }


  /**
   * Actualiza la matriz de color, creando una nueva con los párametros actuales y la asigna a un objeto ColorMatrixFilter, que se añade
   * a la lista de filtros del objeto DisplayObject asociado.
   */
  private function update() : void
  {
    _matrix = new ColorMatrixEx();
    _matrix.adjustColor(_brightness, _contrast, _saturation, _hue);

    EffectUtil.setFilter(target, new ColorMatrixFilter(_matrix));
  }
}
}